Medium 清新閱讀版
:連結
今天來看 Queue Mocking 吧!
Queue::fake()
:當我們希望在執行測試目標行為時,想驗證某個 Job 類別是否有被派送至佇列中,但又不要真的觸發 Job 入列時,可在測試程式碼中呼叫此函數。Queue::assertPushed()
:可驗證指定的 Job 類別是否被配送至佇列。需在執行 Queue::fake()
後方可使用。Queue::assertPushedOn()
:可驗證指定的 Job 類別是否被配送至指定的佇列。需在執行 Queue::fake()
後方可使用。Queue::assertNotPushed()
:可驗證指定的 Job 類別是否未被配送至佇列。需在執行 Queue::fake()
後方可使用。Queue::assertNothingPushed()
:可驗證是否無 Job 類別被配送至佇列。需在執行 Queue::fake()
後方可使用。接下來讓我們實際演練看看吧!
測試目標:文章瀏覽記錄端點
database/migrations/2022_10_02_174939_create_articles_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->text('content');
$table->integer('page_views');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('articles');
}
};
app/Models/Article.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasFactory;
protected $fillable = [
'content',
'page_views',
];
}
database/factories/ArticleFactory.php
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Article>
*/
class ArticleFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition()
{
return [
'content' => $this->faker->text,
'page_views' => 0,
];
}
}
app/Jobs/AddArticlePageViewJob.php
<?php
namespace App\Jobs;
use App\Models\Article;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class AddArticlePageViewJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $article;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(Article $article)
{
$this->article = $article;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$this->article->page_views += 1;
$this->article->save();
}
}
routes\api.php
<?php
use App\Jobs\AddArticlePageViewJob;
use App\Models\Article;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::post('/article/{id}/page-view', function (Request $request, $id) {
$article = Article::find($id);
if (empty($article)) {
return response()->json([], 404);
}
AddArticlePageViewJob::dispatch($article)->onQueue('redis');
return response('', 200);
});
測試程式碼:
<?php
namespace Tests\Feature;
use App\Jobs\AddArticlePageViewJob;
use App\Models\Article;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue;
use Tests\TestCase;
class QueueTest extends TestCase
{
use RefreshDatabase;
public function testDispatchAddArticlePageViewJob()
{
$article = Article::factory()->create();
Queue::fake();
$response = $this->post(route('add-article-page-views', ['id' => $article->id]));
$response->assertOk();
Queue::assertPushedOn('redis', AddArticlePageViewJob::class);
}
public function testNotDispatchAddArticlePageViewJob()
{
$article = Article::factory()->create();
Queue::fake();
$response = $this->post(route('add-article-page-views', ['id' => $article->id . '0']));
$response->assertNotFound();
Queue::assertNotPushed(AddArticlePageViewJob::class);
}
}
以上測試程式碼,測試了 2 種測試案例:
testDispatchAddArticlePageViewJob()
:在這個測試案例函數中,我們驗證了當文章瀏覽記錄端點被請求,且文章存在時,有發送AddArticlePageViewJob
這個 Job 類別。testNotDispatchAddArticlePageViewJob()
:在這個測試案例函數中,我們驗證了當文章瀏覽記錄端點被請求,且文章不存在時,沒有發送AddArticlePageViewJob
這個 Job 類別。以上就是今天所介紹的 Queue Mocking,大家可以多加演練。
明天讓我們來看看Storage Mocking 與 HTTP Mocking。
PS. 大家可以發現,Event、Mail、Queue 這三者的 Mocking方法其實都滿像的,因此將他們三者用類似的方式來介紹。